#pragma once

#include <iostream>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

const std::string nullfile = "/dev/null"; //进行垃圾处理的字符文件

void Daemon(const std::string& cwd = "") {
    //1.忽略其他异常信号
    signal(SIGCLD, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    signal(SIGSTOP, SIG_IGN);

    //将自己变成独立的会话
    if (fork() > 0) exit(0);
    setsid();

    //3.更改当前调用进程的工作目录
    // 守护进程对外提供服务，可能会把头文件等写到系统中，所以工作目录可能会在根目录
    if (!cwd.empty()) chdir(cwd.c_str());

    //4.标准输入，标准输出，标准错误重定向至 /dev/null
    // 守护进程不应该在向标准输出打印。如果关闭0 1 2文件描述符，那么所有打印就会报错。
    // /dev/null 垃圾桶。里面什么都读取不到，向里面写入也会被丢弃
    int fd = open(nullfile.c_str(), O_RDWR);
    if (fd > 0) {
        dup2(fd, 0);
        dup2(fd, 1);
        dup2(fd, 2);
        close(fd);
    }
}